﻿using System;
using EmbeddedSharp.Core;
using Microsoft.VisualStudio.TestTools.UnitTesting;

namespace Zove.Runtime.Test
{
    [TestClass]
    public class ExpressionTests : AbstractTests
    {
        [TestMethod]
        public void TestBasicArithmetics()
        {
            AssertExpression("1+2", 3);
            AssertExpression("1-2", -1);
            AssertExpression("1+1*2/2", 2);
            AssertExpression("2/1", 2);
            AssertExpression("-1", -1);
        }

        [TestMethod]
        public void TestNil()
        {
            AssertExpression("a=nil", null);
        }

        [TestMethod]
        public void TestAbs()
        {
            AssertExpression("abs(2-1)", 1);
            AssertExpression("abs(1-2)", 1);
        }

        [TestMethod]
        public void TestSum()
        {
            AssertExpression("sum(1,2,3,4)", 10);
        }

        [TestMethod]
        public void TestEmbrace()
        {
            AssertExpression("(1+2)/3", 1.0d);
            AssertExpression("(1+2)/(2+1)", 1.0d);
        }

        [TestMethod]
        public void TestSineFunction()
        {
            AssertExpression("cos(1-1)", Math.Cos(0));
            AssertExpression("sin(cos(0))", Math.Sin(1));
            AssertExpression("sum(3,2,1)", 6);
        }

        [TestMethod]
        public void TestNegative()
        {
            AssertExpression("-1", -1);
        }

        [TestMethod]
        public void TestBracket()
        {
            ExpressionParser p = DefaultDependencyManager.Instance.ParserFactory.CreateParser("[1,2,3,4]");
            Node root = p.Parse();

            Assert.AreEqual(typeof(ListNode), root.GetType());
            Assert.AreEqual(4, ((FuncNode)root).Parameters.Count);
        }

        [TestMethod]
        public void TestLogic()
        {
            AssertExpression("1 < 2", true);
            AssertExpression("1 > 2", false);
            AssertExpression("1 <= 2", true);
            AssertExpression("1 >= 2", false);

            AssertExpression("(3 > 2) & (1 < 2)", true);
        }

        [TestMethod]
        public void TestNot()
        {
            AssertExpression("!False", true);
        }

        [TestMethod]
        public void TestNotEqual()
        {
            AssertExpression("3 != 4", true);
            AssertExpression("3 != 3", false);
        }

        [TestMethod]
        public void TestOr()
        {
            AssertExpression("true | false", true);
            AssertExpression("false | false", false);
        }

        [TestMethod]
        public void TestArithmeticAndLogic()
        {
            AssertExpression("true & (1 < 2)", true);
            AssertExpression("(3 + 2*3 > 9) & (1 <= 2)", false);
            //TestExpression("((3 + 2*3*(5) >= 9) & (1 < 2)) | false", false);
            AssertExpression("(3 + 2*3*(5) >= 9 & (1 > 2)) | false", false);
        }

        [TestMethod]
        public void TestFunctionAndLogic()
        {
            AssertExpression("abs(0-1) < 1 | (1 < 2)", true);
        }
    }
}